#include <ctime>
#include <cstdlib>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include "WalkieTalkie.hpp"

namespace pizzeria {
namespace communication {

WalkieTalkie::WalkieTalkie() {
  std::ostringstream oss;

  oss << "/tmp/.Plazza_FIFO_" << clock() << "_" << rand() % 100000;
  mInput = new wrappers::unix_utils::NamedPipe(oss.str());
  mOutput = NULL;
}

WalkieTalkie::~WalkieTalkie() {
  delete mInput;
}

void WalkieTalkie::LinkWith(WalkieTalkie& walkieB) {
  mOutput = walkieB.GetInput();
  walkieB.SetOutput(mInput);
}

void WalkieTalkie::Send(const Message& message) const {
  if (mOutput == NULL)
    throw std::invalid_argument("No linked talkie-walkie");
  std::string data = message.Serialize();
  mOutput->Write<char>(data.c_str(), data.length());
}

Message WalkieTalkie::Receive() const {
  Message message;
  Message::Type type;

  mInput->Read<Message::Type>(&type, sizeof(Message::Type));
  message.SetType(type);
  size_t serializedSize = message.GetSerializedSize() - sizeof(Message::Type);
  char serializedData[serializedSize + 1];
  serializedData[serializedSize] = 0;
  mInput->Read<char>(&serializedData[0], serializedSize);
  message.Deserialize(serializedData);
  return (message);
}

wrappers::unix_utils::NamedPipe*& WalkieTalkie::GetInput() {
  return mInput;
}

void WalkieTalkie::SetOutput(wrappers::unix_utils::NamedPipe*& output) {
  mOutput = output;
}

} /* !namespace communication */
} /* !namespace pizzeria */
